﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.Win32;
using System.Text;

namespace ProjectHelper
{
    /// <summary>
    /// Creates the resource & cs file based on the TfsGiggleETW.man file.
    /// The .res file is copied to the EngineService project which has a resource file dependency on.
    /// The TfsGiggleETW.cs is referenced by Core in the ETW folder. Even if the file is under source control, it is overwritten during the build.
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            const string WindowsSDKCurrentInstallPathKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows";
            var currentInstallFolder = Registry.GetValue(WindowsSDKCurrentInstallPathKey, "CurrentInstallFolder", null);
            if (currentInstallFolder == null)
            {
                throw new KeyNotFoundException("You need to install the Windows SDK for Windows 7");
            }
            var pathToMC = Path.Combine(currentInstallFolder.ToString(), "bin\\mc.exe");
            if (!File.Exists(pathToMC))
            {
                throw new FileNotFoundException(string.Format("The file mc.exe could not be found with the path {0}", currentInstallFolder.ToString()));
            }
            var pathToRC = Path.Combine(currentInstallFolder.ToString(), "bin\\rc.exe");
            if (!File.Exists(pathToRC))
            {
                throw new FileNotFoundException(string.Format("The file rc.exe could not be found with the path {0}", currentInstallFolder.ToString()));
            }
            if (args == null || args.Length < 1)
            {
                throw new ArgumentException("You need to specify the full name for the TfsGiggle manifest file");
            }
            var manifestFile = args[0];
            if (!File.Exists(manifestFile))
            {
                throw new FileNotFoundException("You need to specify the full name of the TfsGiggle manifest file");
            }
            Directory.SetCurrentDirectory(Path.GetDirectoryName(manifestFile));
            var processInfo = new ProcessStartInfo(pathToMC, manifestFile);
            processInfo.CreateNoWindow = false;
            processInfo.LoadUserProfile = true;
            processInfo.RedirectStandardError = true;
            processInfo.UseShellExecute = false;
            processInfo.ErrorDialog = false;

            var process = Process.Start(processInfo);
            process.WaitForExit();

            string standardError;
            using (var sr = process.StandardError)
            {
                standardError = sr.ReadToEnd();
                if (!string.IsNullOrWhiteSpace(standardError))
                {
                    throw new Exception(string.Format("There was an error executing {0}:{1}", processInfo.FileName, standardError));
                }
            }

            // Make sure we can create a new one
            var fi = new FileInfo(Path.GetFileNameWithoutExtension(manifestFile) + ".cs");
            if (fi.Exists)
            {
                fi.IsReadOnly = false;
            }

            // Create the .cs file
            processInfo.Arguments = "-css ETW " + manifestFile;
            process = Process.Start(processInfo);
            process.WaitForExit();

            // XML comment friendly
            var sb = new StringBuilder("#pragma warning disable 1591");
            sb.AppendLine();
            sb.AppendLine(File.ReadAllText(fi.FullName));
            sb.AppendLine("#pragma warning restore 1591");
            File.WriteAllText(fi.FullName, sb.ToString());

            using (var sr = process.StandardError)
            {
                standardError = sr.ReadToEnd();
                if (!string.IsNullOrWhiteSpace(standardError))
                {
                    throw new Exception(string.Format("There was an error executing {0}:{1}", processInfo.FileName, standardError));
                }
            }

            var pathToResourceFile = Path.GetFileNameWithoutExtension(manifestFile) + ".rc";
            if (!File.Exists(pathToResourceFile))
            {
                throw new FileNotFoundException(string.Format("The generated resource '{0}' could not be found", pathToResourceFile));
            }
            processInfo.Arguments = pathToResourceFile;
            processInfo.FileName = pathToRC;
            process = Process.Start(processInfo);
            process.WaitForExit();

            using (var sr = process.StandardError)
            {
                standardError = sr.ReadToEnd();
                if (!string.IsNullOrWhiteSpace(standardError))
                {
                    throw new Exception(string.Format("There was an error executing {0}:{1}", processInfo.FileName, standardError));
                }
            }
            const string ResFile = "TfsGiggleETW.res";
            if (!File.Exists(ResFile))
            {
                throw new FileNotFoundException(ResFile + " was not found");
            }
            var destinationDir = Path.Combine(Path.GetDirectoryName(manifestFile),@"..\..\TfsGiggle.EngineService");
            if( !Directory.Exists(destinationDir))
            {
                throw new DirectoryNotFoundException(destinationDir);
            }
            File.Copy(ResFile, Path.Combine(destinationDir, ResFile), true);
        }
    }
}